package l1j.server.server.model.damage.hit;

import static l1j.server.server.model.skill.L1SkillId.COOKING_2_0_N;
import static l1j.server.server.model.skill.L1SkillId.COOKING_2_0_S;
import static l1j.server.server.model.skill.L1SkillId.COOKING_2_3_N;
import static l1j.server.server.model.skill.L1SkillId.COOKING_2_3_S;
import static l1j.server.server.model.skill.L1SkillId.COOKING_3_0_N;
import static l1j.server.server.model.skill.L1SkillId.COOKING_3_0_S;
import static l1j.server.server.model.skill.L1SkillId.COOKING_3_2_N;
import static l1j.server.server.model.skill.L1SkillId.COOKING_3_2_S;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import l1j.server.L1DatabaseFactory;
import l1j.server.server.model.L1Character;
import l1j.server.server.model.Instance.L1ItemInstance;
import l1j.server.server.model.Instance.L1PcInstance;
import l1j.server.server.serverpackets.S_AttackPacket;
import l1j.server.server.serverpackets.S_UseArrowSkill;
import l1j.server.server.utils.SQLUtil;

//通用於 Pc_Pc,Pc_Npc場合
public class L1PcHit {
	protected static final int[] strHit = new int[255];
	protected static final int[] dexHit = new int[255];
	static {
		Connection con = null;
		PreparedStatement pstm = null;
		ResultSet rs = null;
		try {
			con = L1DatabaseFactory.getInstance().getConnection();
			pstm = con.prepareStatement("select * from x_str_dex");
			rs = pstm.executeQuery();
			while (rs.next()) {
				int i = rs.getInt("value") - 1;
				strHit[i] = rs.getInt("str_hit");
				dexHit[i] = rs.getInt("dex_hit");
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			SQLUtil.close(pstm);
			SQLUtil.close(con);
			SQLUtil.close(rs);
		}
	}

	private L1PcInstance _attacker;
	private L1Character _target;

	public L1PcHit(L1PcInstance attacker, L1Character target) {
		_attacker = attacker;
		_target = target;
	}

	public void doAttackAction() {
		int _attckGrfxId = 0;
		boolean isFly = false;
		_attacker.setHeading(_attacker.targetDirection(_target.getX(),
				_target.getY())); // 改變面向
		L1ItemInstance weapon = _attacker.getWeapon();
		if (weapon != null) {
			if (weapon.isBow()) {
				L1ItemInstance arrow = _attacker.getInventory().getArrow();
				int weaponId = weapon.getItemId();
				if (arrow != null || weaponId == 190) {
					if (arrow != null) { // 弓 - 有箭
						_attacker.getInventory().removeItem(arrow, 1);
						_attckGrfxId = 66; // 箭
					} else if (weaponId == 190) // 沙哈 - 無箭
						_attckGrfxId = 2349; // 魔法箭
					if (_attacker.getTempCharGfx() == 8719) // 柑橘
						_attckGrfxId = 8721; // 橘子籽

					if (_attacker.getTempCharGfx() == 8900) // 海露拜
						_attckGrfxId = 8904; // 魔法箭

					if (_attacker.getTempCharGfx() == 8913) // 朱里安
						_attckGrfxId = 8916; // 魔法箭

					isFly = true;
				}
			} else if (weapon.isGauntlet()) {
				L1ItemInstance sting = _attacker.getInventory().getSting();
				if (sting != null) {
					_attacker.getInventory().removeItem(sting, 1);
					_attckGrfxId = 2989; // 飛刀
					isFly = true;
				}

			}
		}

		int[] data = null;

		if (isFly) { // 遠距離攻擊
			data = new int[] { 1, 0, _attckGrfxId };
			_attacker.sendPackets(new S_UseArrowSkill(_attacker, _target
					.getId(), _target.getX(), _target.getY(), data));
			_attacker.broadcastPacket(new S_UseArrowSkill(_attacker, _target
					.getId(), _target.getX(), _target.getY(), data));
		} else { // 近距離攻擊
			data = new int[] { 1, 0, 0 };
			_attacker.sendPackets(new S_AttackPacket(_attacker,
					_target.getId(), data));
			_attacker.broadcastPacket(new S_AttackPacket(_attacker, _target
					.getId(), data));
		}

	}

	public boolean calcPcHit() {
		int weaponRange = 1;
		int weaponId = 0;
		L1ItemInstance weapon = _attacker.getWeapon();
		if (weapon != null) {
			weaponRange = weapon.getItem().getRange();
			weaponId = weapon.getItemId();
		}
		if (weaponRange != -1) {
			if (_attacker.getLocation().getTileLineDistance(
					_target.getLocation()) > weaponRange + 1) { // BIGのモンスターに対応するため射程範囲+1
				return false;
			}
		} else {
			if (!_attacker.getLocation().isInScreen(_target.getLocation())) {
				return false;
			}
		}
		if (weaponRange != 1 && !_attacker.glanceCheck(_target.getX(), _target.getY())) {
				return false;
		}

		if (weaponId != 0) {
			if ((weapon.isBow() && _attacker.getInventory().getArrow() == null)
					|| (weapon.isGauntlet() && _attacker.getInventory()
							.getSting() == null)) {
				return false;
			} else if ((weaponId == 247) || (weaponId == 248)
					|| (weaponId == 249)) {
				return false;// 試練の剣B～C 攻撃無効
			}
		}
		return true;
	}

	public int calcPcHitRate(int _hitRate) {
		_hitRate = _attacker.getLevel();

		_hitRate += strHit[_attacker.getStr()];

		_hitRate += dexHit[_attacker.getDex()];

		L1ItemInstance weapon = _attacker.getWeapon();
		if (weapon != null) {
			_hitRate += weapon.getItem().getHitModifier()
					+ weapon.getHitByMagic() + (weapon.getEnchantLevel() / 2);
			if (weapon.isBow() || weapon.isGauntlet()) {
				_hitRate = calLongHitRate(_hitRate);
			} else {
				_hitRate = calShortHitRate(_hitRate);
			}
		}

		int weight = _attacker.getInventory().getWeight242();
		if (weight > 80) {
			_hitRate -= 1;
			if (weight > 120) {
				_hitRate -= 2;
				if (weight > 160) {
					_hitRate -= 2;
				}
			}
		}

		return _hitRate;
	}

	private int calShortHitRate(int _hitRate) {
		_hitRate += _attacker.getHitup() + _attacker.getOriginalHitup();
		// 防具增加命中
		_hitRate += _attacker.getHitModifierByArmor();

		if (_attacker.hasSkillEffect(COOKING_2_0_N) // 料理追加命中
				|| _attacker.hasSkillEffect(COOKING_2_0_S))
			_hitRate += 1;
		if (_attacker.hasSkillEffect(COOKING_3_2_N) // 料理追加命中
				|| _attacker.hasSkillEffect(COOKING_3_2_S))
			_hitRate += 2;
		return _hitRate;
	}

	private int calLongHitRate(int _hitRate) {
		_hitRate += _attacker.getBowHitup() + _attacker.getOriginalBowHitup();
		// 防具增加命中
		_hitRate += _attacker.getBowHitModifierByArmor();

		if (_attacker.hasSkillEffect(COOKING_2_3_N) // 料理追加命中
				|| _attacker.hasSkillEffect(COOKING_2_3_S)
				|| _attacker.hasSkillEffect(COOKING_3_0_N)
				|| _attacker.hasSkillEffect(COOKING_3_0_S))
			_hitRate += 1;
		return _hitRate;
	}
}
